/*
 * Copyright 2010 Katsunori Koyanagi
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package sweezy.core.utils
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.system.System;
	import flash.utils.getTimer;

	[Event(name="change", type="flash.events.Event")]
	public class PerformanceProfiler extends EventDispatcher
	{

		public var avarageFrameRate:Number;

		public var currentFrameRate:Number;

		public var currentMemory:int;

		public var maxFrameRate:Number;

		public var maxMemory:int;

		public var minFrameRate:Number;

		public var minMemory:int;

		public var runningTime:int;

		private var _currentTime:int;

		private var _frameCount:int;

		private var _intervalTime:int;

		private var _running:Boolean;

		private var _startTime:int;

		private var _totalCount:int;

		public function PerformanceProfiler()
		{
			reset();
		}

		public function get running():Boolean
		{
			return _running;
		}

		public function start():void
		{
			if (_running)
			{
				return;
			}

			_running = true;
			reset();
			_startTime = _intervalTime = getTimer();
			EventLoop.addHandler(handler);
		}

		public function stop():void
		{
			if (!_running)
			{
				return;
			}

			_running = false;
			EventLoop.removeHandler(handler);
		}

		private function handler(e:Event = null):void
		{
			_currentTime = getTimer();

			_frameCount++;
			_totalCount++;
			runningTime = _currentTime - _startTime;

			var interval:int = _currentTime - _intervalTime;
			if (interval >= 1000)
			{
				var frameRate:Number = currentFrameRate = _frameCount * 1000 / interval;
				var memory:Number = currentMemory = System.totalMemory;

				if (frameRate > 0)
				{
					minFrameRate = minFrameRate === 0 ? frameRate : minFrameRate > frameRate ? frameRate : minFrameRate;
				}
				if (memory > 0)
				{
					minMemory = minMemory === 0 ? memory : minMemory > memory ? memory : minMemory;
				}

				maxFrameRate = maxFrameRate < frameRate ? frameRate : maxFrameRate;
				maxMemory = maxMemory < memory ? memory : maxMemory;
				avarageFrameRate = _totalCount * 1000 / runningTime;

				_intervalTime = _currentTime;
				_frameCount = 0;

				if (hasEventListener(Event.CHANGE))
				{
					dispatchEvent(new Event(Event.CHANGE));
				}
			}
		}

		private function reset():void
		{
			_totalCount = 0;
			_frameCount = 0;

			maxFrameRate = 0;
			minFrameRate = 0;
			avarageFrameRate = 0;
			currentFrameRate = 0;
			currentMemory = 0;
			maxMemory = 0;
			minMemory = 0;
			runningTime = 0;
		}
	}
}
